package com.example.ocr_ui;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.view.PreviewView;
import androidx.constraintlayout.widget.ConstraintLayout;

import com.example.ocr_ui.bean.PictureInfo;
import com.example.ocr_ui.luban.Luban;
import com.example.ocr_ui.luban.OnCompressListener;
import com.example.ocr_ui.util.FormatUtil;
import com.example.ocr_ui.util.PermissionUtils;
import com.example.ocr_ui.util.PictureThreadUtils;
import com.example.ocr_ui.util.StatusBarUtils;
import com.example.ocr_ui.view.CropView;
import com.example.ocr_ui.view.FrameOverlayView;
import com.example.ocr_ui.view.MaskView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author huyi
 */
public class CameraActivity extends AppCompatActivity {
    public static final String KEY_OUTPUT_FILE_PATH = "outputFilePath";
    public static final String KEY_CONTENT_TYPE = "contentType";
    public static final String KEY_CONTENT_BEAN = "contentTypeBean";


    public static final String CONTENT_TYPE_GENERAL = "general";
    public static final String CONTENT_TYPE_ID_CARD_FRONT = "IDCardFront";
    public static final String CONTENT_TYPE_ID_CARD_BACK = "IDCardBack";
    public static final String CONTENT_TYPE_BANK_CARD = "bankCard";
    public static final String CONTENT_TYPE_PASSPORT = "passport";
    public static final String CONTENT_TYPE_HONGKONG = "hongkong";
    public static final String CONTENT_TYPE_CREDITCODE = "creditCode";//统一信用代码

    public static final String CONTENT_TYPE_VEHICLE_LICENSE = "vehiclelicense";//行驶证识别
    public static final String CONTENT_TYPE_LICENSE = "license";//车牌识别
    public static final String CONTENT_TYPE_CERTIFICATE = "certificate";//合格证识别
    public static final String CONTENT_TYPE_INVOICE = "invoice";//新车购置发票
    private String contentType;

    private static final int REQUEST_CODE_PICK_IMAGE = 0X85;
    private static final int PERMISSIONS_REQUEST_CAMERA = 0X86;
    private static final int PERMISSIONS_EXTERNAL_STORAGE = 0X87;
    protected PreviewView previewView;
    private CameraScan mCameraScan;
    protected ImageView ivFlashlight;
    private ImageView takePhoto, album_button;
    private MaskView maskView;
    private CropView crop_view;
    private FrameOverlayView overlay_view;
    private FrameLayout fl_takePhoto, fl_result, fl_title;
    private ImageView cancel_button, confirm_button, rotate_button, ivLeft;
    private TextView tvTitle;
    private String parentPath;//保存图片的目录

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        StatusBarUtils.transparentStatusBar(this);
        setContentView(R.layout.hy_activity_camera);
        initUI();
    }

    /**
     * 初始化
     */
    public void initUI() {
        previewView = findViewById(R.id.previewView);
        ivFlashlight = findViewById(R.id.light_button);
        maskView = findViewById(R.id.maskView);
        takePhoto = findViewById(R.id.take_photo_button);
        album_button = findViewById(R.id.album_button);
        crop_view = findViewById(R.id.crop_view);
        overlay_view = findViewById(R.id.overlay_view);
        fl_takePhoto = findViewById(R.id.fl_takePhoto);
        fl_result = findViewById(R.id.fl_result);
        fl_title = findViewById(R.id.fl_title);
        ivLeft = findViewById(R.id.ivLeft);
        tvTitle = findViewById(R.id.tvTitle);
        cancel_button = findViewById(R.id.cancel_button);
        confirm_button = findViewById(R.id.confirm_button);
        rotate_button = findViewById(R.id.rotate_button);

        ivFlashlight.setOnClickListener(v -> onClickFlashlight());
        takePhoto.setOnClickListener(v -> takePhoto());
        cancel_button.setOnClickListener(v -> cancelButton());
        confirm_button.setOnClickListener(v -> confirmButton());
        album_button.setOnClickListener(v -> albumButton());
        rotate_button.setOnClickListener(v -> rotateButton());
        ivLeft.setOnClickListener(v -> finish());
        initMaskView();
        initCameraScan();
        startCamera();
    }

    private void initMaskView() {
        //设置标题栏在状态栏之下
        ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) fl_title.getLayoutParams();
        layoutParams.topMargin = StatusBarUtils.getStatusBarHeight(this);
        fl_title.setLayoutParams(layoutParams);
        contentType = getIntent().getStringExtra(KEY_CONTENT_TYPE);
        parentPath = getIntent().getStringExtra(KEY_OUTPUT_FILE_PATH);
        if (TextUtils.isEmpty(parentPath)) {
            parentPath = getExternalFilesDir("ocr").getAbsolutePath();
        }
        if (contentType == null) {
            contentType = CONTENT_TYPE_GENERAL;
        }
        int maskType;
        String hint;
        switch (contentType) {
            case CONTENT_TYPE_ID_CARD_FRONT://身份证正面
                maskType = MaskView.MASK_TYPE_ID_CARD_FRONT;
                hint = "身份证正面";
                break;
            case CONTENT_TYPE_ID_CARD_BACK://身份证反面
                maskType = MaskView.MASK_TYPE_ID_CARD_BACK;
                hint = "身份证反面";
                break;
            case CONTENT_TYPE_BANK_CARD://银行卡
                maskType = MaskView.MASK_TYPE_BANK_CARD;
                hint = "银行卡";
                break;
            case CONTENT_TYPE_PASSPORT://护照
                maskType = MaskView.MASK_TYPE_PASSPORT;
                hint = "护照";
                break;
            case CONTENT_TYPE_VEHICLE_LICENSE://行驶证
                maskType = MaskView.MASK_TYPE_VEHICLE_LICENSE;
                hint = "行驶证";
                break;
            case CONTENT_TYPE_HONGKONG://港澳通行证
                maskType = MaskView.MASK_TYPE_HONGKONG;
                hint = "港澳通行证";
                break;
            case CONTENT_TYPE_LICENSE://车牌
                maskType = MaskView.MASK_TYPE_LICENSE;
                hint = "车牌";
                break;
            case CONTENT_TYPE_CERTIFICATE://新车合格证
                maskType = MaskView.MASK_TYPE_NONE;
                hint = "新车合格证";
                break;
            case CONTENT_TYPE_CREDITCODE://统一信用代码
                maskType = MaskView.MASK_TYPE_NONE;
                hint = "统一信用代码";
                break;
            case CONTENT_TYPE_INVOICE://新车购置发票
                maskType = MaskView.MASK_TYPE_NONE;
                hint = "新车购置发票";
                break;
            case CONTENT_TYPE_GENERAL:
            default:
                maskType = MaskView.MASK_TYPE_NONE;
                hint = "";
                break;
        }
        tvTitle.setText(hint);
        maskView.setMaskType(maskType);
        if (maskType == MaskView.MASK_TYPE_NONE) {
            maskView.setVisibility(View.INVISIBLE);
        } else {
            maskView.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 初始化CameraScan
     */
    public void initCameraScan() {
        mCameraScan = new DefaultCameraScan(this, previewView);
        mCameraScan.setPlayBeep(true).setVibrate(true).setPictureSavePath(parentPath).setOnTakePhotoResultCallback(new CameraScan.OnTakePhotoResultCallback() {
            @Override
            public void onTakePhotoResultCallback(String path) {
                showMaskViewOrCropView(path);
            }

            @Override
            public void onTakePhotoResultFailure() {

            }
        });
    }

    /**
     * 截图
     *
     * @param path
     */
    private void showMaskViewOrCropView(String path) {
        comparessImage(path, 1);
        fl_result.setVisibility(View.VISIBLE);
        fl_takePhoto.setVisibility(View.GONE);
        if (mCameraScan != null) {
            mCameraScan.stopCamera();
        }
        if (maskView.getMaskType() == MaskView.MASK_TYPE_NONE) {
            //显示剪切图层
            overlay_view.setVisibility(View.VISIBLE);
        } else {
            overlay_view.setVisibility(View.INVISIBLE);
        }
    }

    /**
     * 压缩图片
     *
     * @param picturePath 图片地址
     * @param type        类型  1，原图压缩  2，剪切的图片压缩
     */
    private void comparessImage(final String picturePath, int type) {
        Luban.with(this)
                .load(picturePath)
                .ignoreBy(1024)
                .setTargetDir(parentPath)
                .setCompressListener(new OnCompressListener() {
                    @Override
                    public void onStart() {
                        Log.d("onstart:::::", "开始图片大小" + FormatUtil.sizeFormatNum2String(new File(picturePath).length()));
                    }

                    @Override
                    public void onSuccess(File file) {
                        // TODO 压缩成功后调用，返回压缩后的图片文件
                        Log.d("onSuccess:::::", "成功后图片大小" + FormatUtil.sizeFormatNum2String(file.length()));
                        if (type == 1) {
                            crop_view.setVisibility(View.VISIBLE);
                            crop_view.setFilePath(file.getAbsolutePath());
                        } else {
                            PictureInfo pictureInfo = new PictureInfo();
                            pictureInfo.setOriginalPath(picturePath);
                            pictureInfo.setCompressPath(file.getAbsolutePath());
                            Intent intent = new Intent();
                            intent.putExtra(KEY_CONTENT_TYPE, contentType);
                            intent.putExtra(KEY_CONTENT_BEAN, pictureInfo);
                            setResult(Activity.RESULT_OK, intent);
                            finish();
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        // TODO 当压缩过程出现问题时调用
                        Log.d("onError:::::", e.getMessage());
                    }
                }).launch();
    }

    /**
     * 启动相机预览
     */
    public void startCamera() {
        if (mCameraScan != null) {
            if (PermissionUtils.checkPermission(this, Manifest.permission.CAMERA)) {
                mCameraScan.startCamera();
            } else {
                PermissionUtils.requestPermission(this, Manifest.permission.CAMERA, PERMISSIONS_REQUEST_CAMERA);
            }
        }
    }


    /**
     * 释放相机
     */
    private void releaseCamera() {
        if (mCameraScan != null) {
            mCameraScan.release();
        }
    }

    /**
     * 拍照
     */
    private void takePhoto() {
        if (mCameraScan != null) {
            mCameraScan.takePhoto();
        }
    }

    /**
     * 相册
     */
    private void albumButton() {
        if (PermissionUtils.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            openAlbum();
        } else {
            PermissionUtils.requestPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSIONS_EXTERNAL_STORAGE);
        }
    }


    /**
     * 点击手电筒
     */
    protected void onClickFlashlight() {
        toggleTorchState();
    }

    /**
     * 切换闪光灯状态（开启/关闭）
     */
    protected void toggleTorchState() {
        if (mCameraScan != null) {
            boolean isTorch = mCameraScan.isTorchEnabled();
            mCameraScan.enableTorch(!isTorch);
            if (ivFlashlight != null) {
                ivFlashlight.setSelected(!isTorch);
            }
        }
    }

    /**
     * 确认
     */
    private void confirmButton() {
        Rect rect;
        if (maskView.getMaskType() == MaskView.MASK_TYPE_NONE) {
            rect = overlay_view.getFrameRect();
        } else {
            rect = maskView.getFrameRect();
        }
        Bitmap cropped = crop_view.crop(rect);
        saveCropView(cropped);
    }

    /**
     * 保存剪切的图片
     *
     * @param bitmap
     */
    private void saveCropView(Bitmap bitmap) {
        PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask<File>() {
            @Override
            public File doInBackground() throws Throwable {
                File file = new File(parentPath, "crop" + System.currentTimeMillis() + ".jpg");
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
                fileOutputStream.close();
                return file;
            }

            @Override
            public void onSuccess(File result) {
                Log.d("onSuccess:::::", "保存剪切图片成功");
                Log.e("保存剪切图片大小", FormatUtil.sizeFormatNum2String(result.length()));
                comparessImage(result.getAbsolutePath(), 2);
            }
        });
    }


    /**
     * 取消
     */
    private void cancelButton() {
        crop_view.setVisibility(View.INVISIBLE);
        crop_view.setFilePath("");
        fl_result.setVisibility(View.GONE);
        fl_takePhoto.setVisibility(View.VISIBLE);
        if (mCameraScan != null) {
            mCameraScan.startCamera();
        }
        if (maskView.getMaskType() == MaskView.MASK_TYPE_NONE) {
            //隐藏剪切图层
            overlay_view.setVisibility(View.INVISIBLE);
        }
    }

    /**
     * 旋转图片
     */
    private void rotateButton() {
        crop_view.rotate(90);
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSIONS_REQUEST_CAMERA) {
            requestCameraPermissionResult(permissions, grantResults);
        }
        if (requestCode == PERMISSIONS_EXTERNAL_STORAGE) {
            requestStorePermissionResult(permissions, grantResults);
        }
    }

    /**
     * 请求Camera权限回调结果
     *
     * @param permissions
     * @param grantResults
     */
    public void requestCameraPermissionResult(@NonNull String[] permissions, @NonNull int[] grantResults) {
        if (PermissionUtils.requestPermissionsResult(Manifest.permission.CAMERA, permissions, grantResults)) {
            startCamera();
        } else {
            showAlertDialog("请在设置中开启拍照权限");
        }
    }

    /**
     * 请求存储权限回调结果
     *
     * @param permissions
     * @param grantResults
     */
    public void requestStorePermissionResult(@NonNull String[] permissions, @NonNull int[] grantResults) {
        if (PermissionUtils.requestPermissionsResult(Manifest.permission.WRITE_EXTERNAL_STORAGE, permissions, grantResults)) {
            openAlbum();
        } else {
            showAlertDialog("请在设置中开启存储权限");
        }
    }


    private void showAlertDialog(String msg) {
        new AlertDialog.Builder(this)
                .setTitle("提示")
                .setMessage(msg)
                .setNegativeButton("确定", (dialog, which) -> finish())
                .setCancelable(false).create().show();
    }

    /**
     * 打开相册
     */
    private void openAlbum() {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
    }

    /**
     * get Context
     *
     * @return this
     */
    protected Context getContext() {
        return this;
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_PICK_IMAGE) {
            if (resultCode == Activity.RESULT_OK) {
                Uri uri = data.getData();
                if (uri == null) {
                    return;
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    copyUriToExternalFilesDir(uri);
                } else {
                    showMaskViewOrCropView(getRealPathFromURI(uri));
                }
            }
        }
    }

    /**
     * 把URI图片复制到当前项目关联的路径里面
     *
     * @param uri
     * @return
     */
    private void copyUriToExternalFilesDir(final Uri uri) {
        PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask<File>() {
            @Override
            public File doInBackground() throws Throwable {
                return copyUriToPath(uri, getContext());
            }

            @Override
            public void onSuccess(File result) {
                showMaskViewOrCropView(result.getAbsolutePath());
            }
        });
    }

    /**
     * 走普通的文件复制流程，拷贝至应用沙盒内来
     *
     * @param uri
     * @param context
     * @return
     */
    private File copyUriToPath(Uri uri, Context context) {
        Log.d("CameraActivity", "正在复制图片中");
        InputStream is = null;
        byte[] buf = new byte[2048];
        FileOutputStream fos = null;
        int len = 0;
        final File file = new File(parentPath, "copy.jpg");
        try {
            is = context.getContentResolver().openInputStream(uri);
            fos = new FileOutputStream(file);
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            fos.flush();
            Log.d("CameraActivity", "复制图片完成");
            Log.d("CameraActivity", "图片大小为：" + FormatUtil.sizeFormatNum2String(file.length()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) is.close();
                if (fos != null) fos.close();
            } catch (IOException e) {
            }
        }
        return file;
    }

    private String getRealPathFromURI(Uri contentURI) {
        String result;
        Cursor cursor = null;
        try {
            cursor = getContentResolver().query(contentURI, null, null, null, null);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        if (cursor == null) {
            result = contentURI.getPath();
        } else {
            cursor.moveToFirst();
            int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            result = cursor.getString(idx);
            cursor.close();
        }
        return result;
    }

    @Override
    protected void onDestroy() {
        releaseCamera();
        super.onDestroy();
    }
}